﻿/// File: ViewletControls\trackbar.fs
/// 
/// Author: Giacomo Righetti (righetti@di.unipi.it)
///   
/// ------------------------------------------------------------
/// Copyright (c) Microsoft Corporation.  All rights reserved.
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------

namespace LightweightControls

open System
open System.Drawing
open System.Windows.Forms
open System.Windows.Forms.VisualStyles

type LightweightTrackBar() =
    inherit LightweightControl()
    
    let defaultMaximum = 10
    let defaultMinimum = 0
    let defaultValue = 0
        
    let defaultSmallChange = 1
    let defaultLargeChange = 5
    
    let trackSize = 4
    let thumbSize = Size(20,20)
    
    let mutable orientation : Orientation = Orientation.Horizontal
    
    let mutable tickStyle = TickStyle.BottomRight
    let mutable tickFrequency = 1
    let mutable ticksEdgeStyle = EdgeStyle.Raised
    
    let mutable maximum = defaultMaximum
    let mutable minimum = defaultMinimum
    let mutable value = defaultValue
    let mutable smallChange = defaultSmallChange
    let mutable largeChange = defaultLargeChange
    
    let thumbRect = Rectangle.Empty
    let trackRect = Rectangle.Empty
    let upperTicksRect = Rectangle.Empty
    let lowerTicksRect = Rectangle.Empty
    
    ///
    /// Summary:
    ///     Gets or sets a value indicating the horizontal or vertical orientation of
    ///     the track bar.
    ///
    /// Returns:
    ///     One of the System.Windows.Forms.Orientation values.
    ///
    member x.Orientation
        with get() = orientation
        and set(v) =
            if v <> orientation then
                orientation <- v
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets a value indicating how to display the tick marks on the track
    ///     bar.
    ///
    /// Returns:
    ///     One of the System.Windows.Forms.TickStyle values. The default is System.Windows.Forms.TickStyle.BottomRight.
    member x.TickStyle
        with get() = tickStyle
        and set(v) = 
            if v <> tickStyle then
                tickStyle <- v
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets a value that specifies the delta between ticks drawn on the
    ///     control.
    ///
    /// Returns:
    ///     The numeric value representing the delta between ticks. The default is 1.
    member x.TickFrequency
        with get() = tickFrequency
        and set(v) = 
            if v <> tickFrequency then
                tickFrequency <- v
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets a value indicating how to display the edges of the ticks on the track.
    ///
    /// Returns:
    ///     One of the System.Windows.Forms.VisualStyles.EdgeStyle values. 
    ///     The default is System.Windows.Forms.VisualStyles.EdgeStyle.Raised.
    member x.TicksEdgeStyle
        with get() = ticksEdgeStyle
        and set(v) = 
            if v <> ticksEdgeStyle then
                ticksEdgeStyle <- v
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets the upper limit of the range this LightweightTrackBar
    ///     is working with.
    ///
    /// Returns:
    ///     The maximum value for the LightweightTrackBar. The default is 10.                       
    member x.Maximum 
        with get() = maximum
        and set(value) = 
            if value <> maximum then
                if value < minimum then    
                    minimum <- value
                    x.setRange(minimum, value)
                    
    ///
    /// Summary:
    ///     Gets or sets the lower limit of the range this LightweightTrackBar
    ///     is working with.
    ///
    /// Returns:
    ///     The minimum value for the LightweightTrackBar. The default is 0. 
    member x.Minimum
        with get() = minimum
        and set(value) = minimum <- value
    
    ///
    /// Summary:
    ///     Gets or sets the value to be added to or subtracted from the Value
    ///     property when the scroll box is moved a small distance.
    ///
    /// Returns:
    ///     A numeric value. The default value is 1.
    ///
    /// Exceptions:
    ///   System.ArgumentOutOfRangeException:
    ///     The assigned value is less than 0.    
    member x.SmallChange
        with get() = smallChange
        and set(value) = 
            if value < 0 then
                raise (ArgumentOutOfRangeException("The assigned value must be greater than or equal to 0."))
            smallChange <- value
    
    ///
    /// Summary:
    ///     Gets or sets a value to be added to or subtracted from the Value
    ///     property when the scroll box is moved a large distance.
    ///
    /// Returns:
    ///     A numeric value. The default is 5.
    ///
    /// Exceptions:
    ///     System.ArgumentException:
    ///       The assigned value is less than 0.
    member x.LargeChange
        with get() = largeChange
        and set(value) = 
            if value < 0 then 
                raise (ArgumentOutOfRangeException("The assigned value must be greater than or equal to 0."))
            largeChange <- value
        
    ///
    /// Summary:
    ///     Gets or sets a numeric value that represents the current position of the
    ///     scroll box on the track bar.
    ///
    /// Returns:
    ///     A numeric value that is within the Minimum and Maximum range. The default value is 0.
    ///
    /// Exceptions:
    ///   System.ArgumentException:
    ///     The assigned value is less than the value of Minimum or the assigned value is greater than the value of Maximum.
    member x.Value
        with get() = value
        and set(v) = 
            if v < minimum || v > maximum then
                raise (ArgumentOutOfRangeException("The assigned value should be between Maximum and Minimum."))
            value <- v      
    
    member private x.setRange (minValue, maxValue) =
        if minimum <> minValue || maximum <> maxValue then
            let mutable maxV = 0
            if minValue > maxValue then
                maxV <- minValue
                minimum <- minValue
                maximum <- maxValue
                base.Invalidate()
            if value < minimum then 
                value <- minimum
            if value > maximum then
                value <- maximum
            x.setTrackBarPosition()
    
    // TODO
    member private x.setTrackBarPosition() = ()
        
    override x.OnPaint(e) = 
        let g = e.Graphics
        
        let numTicks = 10
        let marginX = 15
        let marginY = 15
                
        if orientation = Orientation.Horizontal then
            let trackRect = Rectangle(marginX, marginY, x.Size.Width - 2 * marginX, trackSize)
            let ticksRect = Rectangle(marginX, marginY + 10, x.Size.Width - 2 * marginX, trackSize)
            //trackRect
            //ticksRect.Offset(0,10)
            
            let thumbPosX = int (float32 value * float32 x.Size.Width / float32 (x.Maximum - x.Minimum))
            Console.WriteLine(thumbPosX)
            
           //let thumbRect = Rectangle(thumbPosX + 10, 8, 20, 20)
//            
//            match tickStyle with
//            | TickStyle.Both -> 
//                TrackBarRenderer.DrawHorizontalThumb(g, thumbRect, TrackBarThumbState.Normal)
//            | TickStyle.None | TickStyle.BottomRight -> 
//                TrackBarRenderer.DrawBottomPointingThumb(g, thumbRect, TrackBarThumbState.Normal)
//            | TickStyle.TopLeft -> 
//                TrackBarRenderer.DrawTopPointingThumb(g, thumbRect, TrackBarThumbState.Normal)
//            | _ -> failwith "not implemented"

            TrackBarRenderer.DrawHorizontalTrack(g, trackRect)
            TrackBarRenderer.DrawHorizontalTicks(g, ticksRect, numTicks, ticksEdgeStyle)
            
        else
            let trackRect = Rectangle(0, 0, trackSize, x.Size.Height)
            let thumbRect = Rectangle(0, x.Size.Height / 2, 20, 20)
            match tickStyle with
            | TickStyle.Both -> 
                TrackBarRenderer.DrawVerticalThumb(g, thumbRect, TrackBarThumbState.Normal)
            | TickStyle.None | TickStyle.BottomRight -> 
                TrackBarRenderer.DrawBottomPointingThumb(g, thumbRect, TrackBarThumbState.Normal)
            | TickStyle.TopLeft -> 
                TrackBarRenderer.DrawTopPointingThumb(g, thumbRect, TrackBarThumbState.Normal)
            | _ -> failwith "not implemented"
            TrackBarRenderer.DrawVerticalTrack(g, trackRect)
            //TrackBarRenderer.DrawVerticalTicks(g, x.ClientRectangle, numTicks, ticksEdgeStyle)
        // debug
        g.DrawRectangle(Pens.Black, x.ClientRectangle)